import logging
import structlog
import re
import os
import json
from datetime import datetime
from handle.S2Redis import socketio


class FlaskStructlogHandler(logging.Handler):
    def __init__(self, log_file):
        super().__init__()
        self.log_file = log_file

        # 初始化日志文件为 JSON 数组，确保使用 UTF-8 编码
        if not os.path.exists(self.log_file):
            with open(self.log_file, "w", encoding="utf-8") as f:
                f.write("[]")

    def emit(self, record):
        # 清除 ANSI 转义序列
        ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
        clean_message = ansi_escape.sub('', record.getMessage())

        # 将日志转换为 JSON 格式
        log_entry = {
            "event": "FlaskLog",
            "original_message": clean_message,
            "timestamp": datetime.utcnow().isoformat() + "Z",  # 获取当前 UTC 时间戳
            "level": record.levelname.lower(),
        }

        # 将日志写入文件，使用 UTF-8 编码处理中文
        with open(self.log_file, "r+", encoding="utf-8") as f:
            f.seek(0, os.SEEK_END)
            f_size = f.tell()
            if f_size > 1:  # 如果文件已有内容，则追加逗号
                f.seek(f_size - 1)
                f.truncate()
                f.write(",\n")
            else:
                f.seek(0)
                f.truncate()
                f.write("[\n")
            json.dump(log_entry, f, indent=4, ensure_ascii=False)  # ensure_ascii=False 保留中文字符
            f.write("\n]")

        # 使用 socketio 实时发送日志
        socketio.emit("log", log_entry)


class Logger:
    def __init__(self, log_file="structured_logs.json"):
        """
        初始化 Logger，配置 structlog 和 Flask 日志处理器
        :param log_file: 日志文件路径
        """
        self.log_file = log_file
        self._configure_standard_logging()
        self._configure_structlog()
        self._patch_flask_logger()

    def _configure_standard_logging(self):
        """配置标准 Python logging"""
        logging.basicConfig(
            level=logging.INFO,
            format="%(message)s",
            handlers=[
                logging.StreamHandler()  # 控制台输出
            ]
        )

    @staticmethod
    def _configure_structlog():
        """配置 structlog"""
        structlog.configure(
            processors=[
                structlog.processors.TimeStamper(fmt="iso"),         # 添加时间戳
                structlog.stdlib.add_log_level,                     # 添加日志级别
                structlog.processors.JSONRenderer(indent=4, ensure_ascii=False),  # 格式化为 JSON，保留中文字符
            ],
            context_class=dict,
            logger_factory=structlog.stdlib.LoggerFactory(),
            wrapper_class=structlog.stdlib.BoundLogger,
            cache_logger_on_first_use=True,
        )

    def _patch_flask_logger(self):
        """替换 Flask 和 Werkzeug 日志器，封装成 structlog"""
        # 替换 werkzeug 日志器
        werkzeug_logger = logging.getLogger("werkzeug")
        werkzeug_logger.handlers.clear()  # 清理默认处理器
        werkzeug_logger.addHandler(FlaskStructlogHandler(self.log_file))
        werkzeug_logger.propagate = False  # 禁止日志传播

        # 替换根日志器
        root_logger = logging.getLogger()
        root_logger.setLevel(logging.INFO)
        root_logger.handlers.clear()
        root_logger.addHandler(FlaskStructlogHandler(self.log_file))

    @staticmethod
    def get_logger(name=None):
        """
        获取 structlog 日志器
        :param name: 日志器名称
        :return: structlog logger 实例
        """
        return structlog.get_logger(name)


# 初始化 Logger
Logger(log_file="structured_logs.json")

# 获取日志器
logger = Logger.get_logger("flask")
